﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Collections.Generic;

namespace Socket_Connect
{
    public class ClientData
    {
        IPAddress
            _IP;

        ushort
            _Port;

        public IPAddress IP
        {
            get { return _IP; }
            set { _IP = value; }
        }

        public ushort Port
        {
            get { return _Port; }
            set { _Port = value; }
        }

        public ClientData(IPAddress IP, ushort Port)
        {
            this._IP = IP;
            this._Port = Port;
        }

        public override string ToString()
        {
            return string.Format("{0}:{1}", this._IP.ToString(), this._Port);
        }
    }

    public class tinSocket
    {
        string
            Rx = "";

        IPAddress
            _ServerIP = IPAddress.Parse("127.0.0.1");

        List<ClientData>
            _ClientList = new List<ClientData>();


        ushort
            _ServerPort = 1124;

        public IPAddress ServerIP
        {
            get { return _ServerIP; }
            set { _ServerIP = value; }
        }

        public ushort ServerPort
        {
            get { return _ServerPort; }
            set { _ServerPort = value; }
        }

        public List<ClientData> ClientList
        {
            get { return _ClientList; }
            set { _ClientList = value; }
        }

        #region Event
        // OnRx 
        public delegate void OnRxEventHandler(string Rx);
        public event OnRxEventHandler OnRxEvent = null;

        // OnServer State Change
        public delegate void OnServerStateChangeEventHandler(bool State);
        public event OnServerStateChangeEventHandler OnServerStateChangeEvent = null;
        #endregion

        public tinSocket()
        {

        }

        ~tinSocket()
        {
            if (socketServer != null)
                EndListen();

            OnRxEvent = null;
            OnServerStateChangeEvent = null;

            ClientList.Clear();
        }

        #region Client
        public void BeginSend(IPAddress ip, int port, string sendtext)
        {
            byte[]
                byteMessage;

            Socket
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            
            socket.Connect(ip, port);

            byteMessage = Encoding.UTF8.GetBytes(sendtext);
            socket.Send(byteMessage);
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();

            System.Threading.Thread.Sleep(10);
        }

        public void BeginSend(string sendtext)
        {
            foreach (ClientData c in ClientList)
            {
                BeginSend(c.IP, c.Port, sendtext);
            }
        }
        #endregion

        #region Server
        delegate void SetTextCallback(byte[] data);

        Thread
            socketServer = null;
        Socket
            socketListener = null;

        public void BeginListen()
        {
            if (socketServer != null)
                return;

            socketServer = new Thread(new ParameterizedThreadStart(this.Listen));
            socketServer.Start(null);
            socketServer.IsBackground = true;
        }
                
        private void Listen(object obj)
        {
            IPEndPoint hostEP = new IPEndPoint(this._ServerIP, this._ServerPort);
            socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socketListener.Bind(hostEP);
            socketListener.Listen(100);

            if (OnServerStateChangeEvent != null)
                OnServerStateChangeEvent(true);

            while (true)
            {
                try
                {
                    Socket NewSocket = socketListener.Accept();
                    byte[] bytesReceive = new byte[1024];
                    NewSocket.Receive(bytesReceive);

                    Rx = Encoding.UTF8.GetString(bytesReceive);

                    if (OnRxEvent != null)
                        OnRxEvent(Rx);

                    NewSocket.Shutdown(SocketShutdown.Both);
                    NewSocket.Close();

                    System.Threading.Thread.Sleep(10);
                }
                catch (System.Threading.ThreadAbortException)
                { }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        public void EndListen()
        {
            socketListener.Close();
            socketServer.Abort();

            socketServer = null;

            if (OnServerStateChangeEvent != null)
                OnServerStateChangeEvent(false);
        }

        #endregion
    }
}